package com.hzjq.core.parse

import android.annotation.SuppressLint
import android.text.TextUtils
import com.hzjq.core.BlastDelegate
import com.hzjq.core.bean.AlongCapResultEntity
import com.hzjq.core.bean.CapEntity
import com.hzjq.core.bean.CapProgressEntity
import com.hzjq.core.bean.Param
import com.hzjq.core.util.CapUtil
import com.hzjq.core.util.Convert
import com.sdk.DeviceManager_LXR5000.util.ByteUtil
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers
import java.io.DataInputStream
import java.io.File
import java.io.FileInputStream

class Parser : ParseLoader {

    override fun parseVersionMsg(msg: String): Int {
        if (msg.length >= 16) {
            return Integer.valueOf(msg.substring(12, 16), 16)
        }
        return 0
    }

    override fun parseUpgradeModeMsg(msg: String): Boolean {
        if (!TextUtils.isEmpty(msg) && msg.length >= 12) {
            val code = msg.substring(4, 6)
            if (TextUtils.equals(code, BlastDelegate.getDelegate().getCmdType())) {
                return true
            }
        }
        return false
    }

    @SuppressLint("CheckResult")
    override fun parseUpgradeFileData(
        binFile: File,
        mSectorDataList: ArrayList<String>,
        mSectorAddrList: ArrayList<String>,
        onNext: Consumer<Boolean>
    ) {
        Observable.create<Boolean> {
            DataInputStream(FileInputStream(binFile)).use { dataStream ->
                val block = ByteArray(2048)
                while (dataStream.read(block) != -1) {
                    mSectorDataList.add(ByteUtil.bytesToHexString(block))
                    mSectorAddrList.add(CapUtil.getCRC_16(block))
                }
                dataStream.close()
                it.onNext(true)
            }
        }.observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.newThread())
            .doOnError {
                onNext.accept(false)
            }.subscribe(onNext)
    }

    override fun parseScanProgress(msg: String): CapProgressEntity {
        val errorCode: String = msg.substring(20, 22)
        val progress = Integer.valueOf(msg.substring(22, 24), 16)
        val total = Integer.valueOf(msg.substring(24, 28), 16)
        val stateCode = Integer.valueOf(msg.substring(28, 30), 16)
        val mVoltage = Integer.valueOf(msg.substring(12, 16), 16) * 1.0
        val mElectric = Integer.valueOf(msg.substring(16, 20), 16) * 1.0
        return CapProgressEntity(
            errorCode, progress, total, stateCode, (mVoltage / 10f).toFloat(),
            (mElectric / 10f).toFloat()
        )
    }

    override fun parseCap(msg: String): MutableList<CapEntity> {
        val data = arrayListOf<CapEntity>()
        val capsData = msg.subSequence(22, msg.length - 2).toString()
        val total = Integer.valueOf(msg.substring(20, 22), 16)
        var startPadding = 0
        for (i in 0 until total) {

            val item = CapEntity()
            item.capNumber = Integer.valueOf(msg.substring(12, 16), 16).toString()

            val uidStart = startPadding
            val uidEnd =  16 + startPadding
            item.uid = capsData.substring(uidStart, uidEnd)

            val pwdStart = uidEnd
            val pwdEnd = uidEnd+8
            item.password = capsData.substring(pwdStart, pwdEnd)

            val delayStart = pwdEnd
            val delayEnd = pwdEnd+4
            item.delay = Integer.valueOf(capsData.substring(delayStart, delayEnd), 16).toLong()

            val statusStart = delayEnd
            val endStatus = delayEnd+2
            item.status = Convert.HexToBin8(capsData.substring(statusStart, endStatus))

            item.total = Integer.valueOf(msg.substring(16, 20), 16)
            item.convertUid = BlastDelegate.getDelegate().getOnCapUidConvertor().convert(item)

            data.add(item)

            startPadding = endStatus
        }
        return data
    }

    override fun parseAlongCap(msg: String): AlongCapResultEntity {
        val item = AlongCapResultEntity()
        val mVoltage = Integer.valueOf(msg.substring(12, 16), 16)
        val mElectric = Integer.valueOf(msg.substring(16, 20), 16)
        item.mElectric = mElectric
        item.mVoltage = mVoltage / 10.0f
        if (msg.length > 36) {
            val uid = msg.substring(20, 36)
            item.uid = uid
        } else {
            if (msg.length > 24) {
                item.error = Integer.parseInt(msg.substring(22, 24), 16)
            } else {
                item.error = -1
            }
        }
        return item
    }

    override fun parseParam(msg: String): Param {
        val param = Param()
        if (msg.length < 37) {
            param.isSuccess = false
            return param
        }
        param.isSuccess = true
        param.signalVoltage = Convert.HexToInt(msg.substring(12, 14))
        param.chargeVoltage = Convert.HexToInt(msg.substring(14, 16))
        param.queryVoltage = Convert.HexToInt(msg.substring(16, 18))
        param.chargeAdc = Convert.HexToInt(msg.substring(18, 20))
        param.blastAdc = Convert.HexToInt(msg.substring(20, 22))
        param.blastCutPower = Convert.HexToInt(msg.substring(22, 24))
        param.groupChargeCount = Convert.HexToInt(msg.substring(24, 26))
        param.groupChargeSleepTime = Convert.HexToInt(msg.substring(26, 28))
        param.reserve1 = Convert.HexToInt(msg.substring(28, 30))
        param.reserve2 = Convert.HexToInt(msg.substring(30, 32))
        param.reserve3 = Convert.HexToInt(msg.substring(32, 34))
        param.reserve4 = Convert.HexToInt(msg.substring(34, 36))
        return param
    }
}